package com.tiancheng.trade.settlement.task;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tiancheng.trade.settlement.feign.OrderService;
import com.tiancheng.trade.settlement.model.settlement.PaymentOrderBank;
import com.tiancheng.trade.settlement.model.settlement.PaymentOrderFinish;
import com.tiancheng.trade.settlement.service.settlement.IReconciliationService;
import com.tiancheng.trade.settlement.util.JacksonJsonUtil;
import com.tiancheng.trade.settlement.vo.settlement.api.PaymentBillVO;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Auther: liudong
 * @Date: 2024/3/31 15:31
 * @Param ${tags}
 * @Description:
 */
@Component
@Slf4j
public class CheckAccountTask {
    @Autowired
    IReconciliationService reconciliationService;
    @Resource
    private JacksonJsonUtil jacksonJsonUtil;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private OrderService orderService;
    /**
     * redis锁.
     */
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 功能描述: 定时对账,每天凌晨1点-2点执行，10秒执行一次
     * 1、每次获取1000条数据对账数据（银行侧数据）
     * 2、判断银行侧数据是否存在，如果不存在不进行对账
     * 3、用银行侧对应的flowId获取中心侧正确数据
     * 4、对比出异常数据，查询出异常数据
     * 5、保存对账结果数据，更新中心侧和银行侧数据对账状态为已对账
     * 6、银行侧待对账数据为空时，查询中心侧待对账数据是否存在，如果存在保存成异常订单
     *
     * @param:
     * @return:
     * @auther: LiuDong
     * @date: 15:32 2024/3/31
     */
//	@Scheduled(cron = "0/10 * 1-2 * * ?")
//	@Scheduled(initialDelay = 12000, fixedRate = 6000)
    @XxlJob("checkReconciliation")
    public ReturnT<String> checkReconciliation(String param) {
        log.info("定时流水对账 开始");
        try {
            Integer year = LocalDate.now().getYear();
            Integer month = LocalDate.now().getMonthValue();
            Integer day = LocalDate.now().getDayOfMonth();
            String key = year + "_" + month + "_" + day;
            String value = year + "" + month + "" + day;
            if (stringRedisTemplate.opsForValue().setIfAbsent(key, value)) {
                //设置锁的时间为150秒，两分半钟
                stringRedisTemplate.expire(key, 150, TimeUnit.SECONDS);
            }
            //获取银行侧待对账数据
            List<PaymentOrderBank> bankOrders = reconciliationService.getBankCheckOrders();
            List<String> orderIds = bankOrders.stream().map(PaymentOrderBank::getPayChannelOrderid).collect(Collectors.toList());
            log.info("银行侧的待对账订单id{}", orderIds.toString());
            //银行侧数据为空的时候，判断中心侧是否有数据
            if (!bankOrders.isEmpty()) {
                //根据银行侧数据对账，获取完成对账数据（对账异常+对账正常）
                List<PaymentOrderFinish> finishList = reconciliationService.bankReconciliation(orderIds);
                //批量保存对账后的数据和更新中心侧和银行侧数据对账状态
                if (!finishList.isEmpty()) {
                    finishList.stream().forEach(orderFinish -> orderFinish.setReconciliationDate(LocalDate.now()));
                    reconciliationService.batchSavePaymentOrders(finishList, orderIds);
                }
            } else {
                //中心侧有数据，银行侧无数据，记录异常订单（数据未匹配）
                reconciliationService.settlementReconciliation();
            }
            log.info("定时流水对账 结束");
        } catch (Exception e) {
            log.error("定时对账 is fail", e, e);
        }
        return ReturnT.SUCCESS;
    }


    /**
     * 功能描述: 异常订单定时去订单中心获取数据进行比较
     * 1、获取银行侧有数据中心侧无数据的异常账单，获取flow_id为空的数据取出全部异常数据
     * 2、如果获取到数据，进行记账操作--调用流水对账接口进行对账--更新对账状态（因为完成对账表数据已经存在，所以进行更新操作）
     * 3、未取到数据，更新对账次数
     *
     * @param:
     * @return:
     * @auther: LiuDong
     * @date: 14:21 2024/4/16
     */
//	@Scheduled(initialDelay = 12000, fixedRate = 6000)
    @XxlJob("callBackCheckReconciliation")
    public ReturnT<String> callBackCheckReconciliation(String param) {
        long startTime = System.currentTimeMillis();
        try {
            Integer year = LocalDate.now().getYear();
            Integer month = LocalDate.now().getMonthValue();
            Integer day = LocalDate.now().getDayOfMonth();
            String key = year + "_" + month + "_" + day;
            String value = year + "" + month + "" + day;
            if (stringRedisTemplate.opsForValue().setIfAbsent(key, value)) {
                //设置锁的时间为150秒，两分半钟
                stringRedisTemplate.expire(key, 150, TimeUnit.SECONDS);
                //获取银行侧有数据中心侧无数据的异常账单
                List<PaymentOrderFinish> unusualList = reconciliationService.getUnusualBankOrders();
                List<String> bankOrderIds = unusualList.stream().map(PaymentOrderFinish::getBankFlowId).collect(Collectors.toList());
                log.info("流水异常订单 data：{}", jacksonJsonUtil.toJson(unusualList));
                //TODO 调用订单中心查询订单接口
//				orderService
                List<PaymentBillVO> accountVOS = objectMapper.readValue("", new TypeReference<List<PaymentBillVO>>() {
                });
                log.info("补充流水记账数据 data:{}", jacksonJsonUtil.toJson(accountVOS));
                //根据银行侧数据对账，获取完成对账数据（对账异常+对账正常）
                List<PaymentOrderFinish> finishList = reconciliationService.bankReconciliation(bankOrderIds);
            }

        } catch (JsonProcessingException e) {
            log.info("流水异常订单回调 is fail", e, e);
        }
        long endTime = System.currentTimeMillis();
        log.info("程序运行时间： " + (endTime - startTime) + "ms");
        return ReturnT.SUCCESS;
    }
}
